<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>

                    <h4>使用模块</h4>
                    <div class="x-wiki-info"><span>2307次阅读</span></div>
                    <hr style="border-top-color:#ccc" />
                    <div class="x-wiki-content x-content"><p>Python本身就内置了很多非常有用的模块，只要安装完毕，这些模块就可以立刻使用。</p>
<p>我们以内建的<code>sys</code>模块为例，编写一个<code>hello</code>的模块：</p>
<pre><code>#!/usr/bin/env python
# -*- coding: utf-8 -*-

&#39; a test module &#39;

__author__ = &#39;Michael Liao&#39;

import sys

def test():
    args = sys.argv
    if len(args)==1:
        print &#39;Hello, world!&#39;
    elif len(args)==2:
        print &#39;Hello, %s!&#39; % args[1]
    else:
        print &#39;Too many arguments!&#39;

if __name__==&#39;__main__&#39;:
    test()
</code></pre><p>第1行和第2行是标准注释，第1行注释可以让这个<code>hello.py</code>文件直接在Unix/Linux/Mac上运行，第2行注释表示.py文件本身使用标准UTF-8编码；</p>
<p>第4行是一个字符串，表示模块的文档注释，任何模块代码的第一个字符串都被视为模块的文档注释；</p>
<p>第6行使用<code>__author__</code>变量把作者写进去，这样当你公开源代码后别人就可以瞻仰你的大名；</p>
<p>以上就是Python模块的标准文件模板，当然也可以全部删掉不写，但是，按标准办事肯定没错。</p>
<p>后面开始就是真正的代码部分。</p>
<p>你可能注意到了，使用<code>sys</code>模块的第一步，就是导入该模块：</p>
<pre><code>import sys
</code></pre><p>导入<code>sys</code>模块后，我们就有了变量<code>sys</code>指向该模块，利用<code>sys</code>这个变量，就可以访问<code>sys</code>模块的所有功能。</p>
<p><code>sys</code>模块有一个<code>argv</code>变量，用list存储了命令行的所有参数。<code>argv</code>至少有一个元素，因为第一个参数永远是该.py文件的名称，例如：</p>
<p>运行<code>python hello.py</code>获得的<code>sys.argv</code>就是<code>[&#39;hello.py&#39;]</code>；</p>
<p>运行<code>python hello.py Michael</code>获得的<code>sys.argv</code>就是<code>[&#39;hello.py&#39;, &#39;Michael]</code>。</p>
<p>最后，注意到这两行代码：</p>
<pre><code>if __name__==&#39;__main__&#39;:
    test()
</code></pre><p>当我们在命令行运行<code>hello</code>模块文件时，Python解释器把一个特殊变量<code>__name__</code>置为<code>__main__</code>，而如果在其他地方导入该<code>hello</code>模块时，<code>if</code>判断将失败，因此，这种<code>if</code>测试可以让一个模块通过命令行运行时执行一些额外的代码，最常见的就是运行测试。</p>
<p>我们可以用命令行运行<code>hello.py</code>看看效果：</p>
<pre><code>$ python hello.py
Hello, world!
$ python hello.py Michael
Hello, Michael!
</code></pre><p>如果启动Python交互环境，再导入<code>hello</code>模块：</p>
<pre><code>$ python
Python 2.7.5 (default, Aug 25 2013, 00:04:04) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
&gt;&gt;&gt; import hello
&gt;&gt;&gt;
</code></pre><p>导入时，没有打印<code>Hello, word!</code>，因为没有执行<code>test()</code>函数。</p>
<p>调用<code>hello.test()</code>时，才能打印出<code>Hello, word!</code>：</p>
<pre><code>&gt;&gt;&gt; hello.test()
Hello, world!
</code></pre><h3 id="-">别名</h3>
<p>导入模块时，还可以使用别名，这样，可以在运行时根据当前环境选择最合适的模块。比如Python标准库一般会提供<code>StringIO</code>和<code>cStringIO</code>两个库，这两个库的接口和功能是一样的，但是<code>cStringIO</code>是C写的，速度更快，所以，你会经常看到这样的写法：</p>
<pre><code>try:
    import cStringIO as StringIO
except ImportError: # 导入失败会捕获到ImportError
    import StringIO
</code></pre><p>这样就可以优先导入<code>cStringIO</code>。如果有些平台不提供<code>cStringIO</code>，还可以降级使用<code>StringIO</code>。导入<code>cStringIO</code>时，用<code>import ... as ...</code>指定了别名<code>StringIO</code>，因此，后续代码引用<code>StringIO</code>即可正常工作。</p>
<p>还有类似<code>simplejson</code>这样的库，在Python 2.6之前是独立的第三方库，从2.6开始内置，所以，会有这样的写法：</p>
<pre><code>try:
    import json # python &gt;= 2.6
except ImportError:
    import simplejson as json # python &lt;= 2.5
</code></pre><p>由于Python是动态语言，函数签名一致接口就一样，因此，无论导入哪个模块后续代码都能正常工作。</p>
<h3 id="-">作用域</h3>
<p>在一个模块中，我们可能会定义很多函数和变量，但有的函数和变量我们希望给别人使用，有的函数和变量我们希望仅仅在模块内部使用。在Python中，是通过<code>_</code>前缀来实现的。</p>
<p>正常的函数和变量名是公开的（public），可以被直接引用，比如：<code>abc</code>，<code>x123</code>，<code>PI</code>等；</p>
<p>类似<code>__xxx__</code>这样的变量是特殊变量，可以被直接引用，但是有特殊用途，比如上面的<code>__author__</code>，<code>__name__</code>就是特殊变量，<code>hello</code>模块定义的文档注释也可以用特殊变量<code>__doc__</code>访问，我们自己的变量一般不要用这种变量名；</p>
<p>类似<code>_xxx</code>和<code>__xxx</code>这样的函数或变量就是非公开的（private），不应该被直接引用，比如<code>_abc</code>，<code>__abc</code>等；</p>
<p>之所以我们说，private函数和变量“不应该”被直接引用，而不是“不能”被直接引用，是因为Python并没有一种方法可以完全限制访问private函数或变量，但是，从编程习惯上不应该引用private函数或变量。</p>
<p>private函数或变量不应该被别人引用，那它们有什么用呢？请看例子：</p>
<pre><code>def _private_1(name):
    return &#39;Hello, %s&#39; % name

def _private_2(name):
    return &#39;Hi, %s&#39; % name

def greeting(name):
    if len(name) &gt; 3:
        return _private_1(name)
    else:
        return _private_2(name)
</code></pre><p>我们在模块里公开<code>greeting()</code>函数，而把内部逻辑用private函数隐藏起来了，这样，调用<code>greeting()</code>函数不用关心内部的private函数细节，这也是一种非常有用的代码封装和抽象的方法，即：</p>
<p>外部不需要引用的函数全部定义成private，只有外部需要引用的函数才定义为public。</p>
</div>

                    <hr style="border-top-color:#ccc" />

                    